/******************************************************************************
 * Copyright 2022 The Rxbit Authors. All Rights Reserved.
 *
 * 理工睿行雷达
 *****************************************************************************/

#pragma once

#include "base/device_connect/radar/device_base.h"

#include "blockingconcurrentqueue.h"
#include "concurrentqueue.h"
#include "rxbit_parser.h"
#include "rxbit_protocol.h"

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <chrono>
#include <iostream>
#include <map>
#include <unistd.h>
#include <unordered_map>
#include <vector>
#define BUFFER_SZ 65507

namespace os
{
    namespace v2x
    {
        namespace device
        {
            // typedef struct
            // {
            //     int32_t fd;
            //     std::string ip;
            //     uint16_t port;
            //     std::string tmsr_sn;
            //     std::string airos_sn;
            //     // os::v2x::device::rxbit::RxbitParser parser;
            // } RadarInformation;
            class Msg
            {
            public:
                int32_t fd;

                u_char data[BUFFER_SZ];
                int32_t dataSize;

                RxbitRadarPackageHead *header;

                Msg()
                {
                    
                    header = nullptr;
                }

                ~Msg()
                {
                    free(header);
                }
            };
            class RadarInformation
            {
            public:
                int32_t fd;
                std::string ip;
                uint16_t port;
                std::string tmsr_sn;
                std::string airos_sn;
                std::shared_ptr<os::v2x::device::RxbitParser> parser;

                RadarInformation()
                {
                }

                ~RadarInformation()
                {
                    // delete parser;
                }
            };

            /**
             * @brief 演示如何注册一个Radar设备到Radar工厂
             *
             */

            class RxbitRadar : public RadarDevice
            {
            public:
                RxbitRadar(const RadarCallBack &cb) : RadarDevice(cb) {}

                virtual ~RxbitRadar() = default;

                bool Init(const std::string &config_file) override;

                void Start() override;

                RadarDeviceState GetState() override { return RadarDeviceState::RUNNING; }

            private:
                std::thread EpollProcessThread();
                std::thread SendMsgThread();

                moodycamel::BlockingConcurrentQueue<std::shared_ptr<Msg>> data_queue;

                int32_t epoll_fd{-1};
                struct epoll_event events[1024]; // while kernel send events , which will be written in here

                struct sockaddr_in server_addr;
                int32_t server_port{0}; // 服务端端口
                int32_t server_fd{-1};  // 服务端fd

                std::string device_vendor;
                std::string cross_id;
                std::string device_firmware;

                std::unordered_map<int32_t, std::string> fd_sn_map;
                std::unordered_map<std::string, RadarInformation> radar_map;
                // std::vector<std::string> device_ips;
                // std::vector<std::string> tmsr_sn;
                // std::vector<std::string> airos_sn;

                uint32_t msg_sequence_num{0}; // message sequence num

                // parse data to protobuf and sender()
                void DataParse(const u_char *data, int32_t dataSize, int32_t fd);

                /**
                 * @brief socket recv接收数据函数
                 * @author 9426224
                 * @date 2022-09-30
                 *
                 * @param server_name 使用该函数的server名称
                 * @param fd recv使用的fd
                 * @param buffer 接收使用的buffer指针
                 * @param buffer_size 应接收的数据量
                 * @param _flags recv使用的参数
                 * @return recv_num 接收到的数据总量 如果不等于buffer_size 则说明recv有误
                 */
                int32_t Receive(std::string server_name, int32_t fd, void *buffer, int32_t buffer_size, int32_t _flags)
                {
                    int32_t recv_num = 0, ret = 0, try_times = 0;

                    while (recv_num < buffer_size)
                    {
                        ret = recv(fd, (u_char *)buffer, buffer_size - recv_num, _flags);
                        try_times++;

                        if (try_times == 2)
                        {
                            break;
                        }

                        if (ret == 0)
                        {
                            continue;
                        }
                        else if (ret == -1)
                        {
                            printf("%s: Value of errno: %d\n", server_name.c_str(), errno);
                            printf("%s: Socket error: %s\n", server_name.c_str(), strerror(errno));
                            recv_num = ret;
                            break;
                        }

                        recv_num += ret;
                    }

                    return recv_num;
                }
            };

        } // namespace device
    }     // namespace v2x
} // namespace os
